package com.jsite.modules.flowable.utils;

import com.jsite.common.lang.StringUtils;
import com.jsite.modules.flowable.entity.FormData;
import com.jsite.modules.flowable.entity.TaskNode;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

public class FormUtils {

    public static String parseForm(String form, List<FormData> data, List<TaskNode> nodeList, String taskDefKey) {
        Document doc = null;
        try {
            form = form.replace("&lt;", "<");
            form = form.replace("&quot;", "\"");
            form = form.replace("&ldquo;", "\"");
            form = form.replace("&rdquo;", "\"");
            form = form.replace("&gt;", ">");
            form = form.replace("&amp;amp;#39;", "\'");
            form = form.replace("&amp;#39;", "\'");
            doc = DocumentHelper.parseText("<div>" + form + "</div>");
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        listNodes(doc.getRootElement(), data, nodeList, taskDefKey);
        return doc.getRootElement().asXML().replace("&amp;lt;","<").replace("&amp;gt;",">").replace("&amp;nbsp;"," ");


}

    private static void listNodes(Element node, List<FormData> data, List<TaskNode> nodeList, String taskDefKey) {
        // 当前节点下面子节点迭代器
        Iterator<Element> it = node.elementIterator();
        // 遍历
        while (it.hasNext()) {
            Element e = it.next();
            elementMethod(e, data, nodeList, taskDefKey);

            listNodes(e, data, nodeList, taskDefKey);
        }
    }

    private static void elementMethod(Element node, List<FormData> data, List<TaskNode> nodeList, String taskDefKey) {
        if(node.getName().equals("table")) {
            node.addAttribute("class", "table-view");
        }

        Attribute atr;
        // input 动态绑定数据
        List<Element> inputElmts = node.elements("input");
        for (Element element : inputElmts) {
            String key = element.attribute("name").getValue();

            if (key.equals("attachmentTable")) {
                Element p = element.getParent();

                Element div = element.getParent().addElement("div");
                Element table = div.addElement("table");
                table.addAttribute("id", "dataGrid");
                table.setText(" ");

                p.remove(element);
                continue;
            }

            String eleValue = data == null ? "" : formDataValue(key, data);

            atr = element.attribute("type");
            if(atr != null && atr.getValue().equals("radio")) {
                Attribute atrRadio = element.attribute("value");
                if(atrRadio.getValue().equals(eleValue)) {
                    element.addAttribute("checked", "checked");
                }
                continue;
            }
            if(atr != null && atr.getValue().equals("checkbox")) {
                Attribute atrCheckBox = element.attribute("value");
                if(atrCheckBox.getValue().equals(eleValue)) {
                    element.addAttribute("checked", "checked");
                }
                continue;
            }

            Attribute temp = element.attribute("orgrequired");
            if(temp != null && temp.getValue().equals("1")) {
                element.addAttribute("class", "required ");
            }
            temp = element.attribute("orgtype");
            if(temp != null && (temp.getValue().equals("int") || temp.getValue().equals("float"))) {
                element.addAttribute("class", "number ");
            }

            element.addAttribute("value", eleValue);

            if(formAuthorizeRead(key, nodeList, taskDefKey)) {
                element.addAttribute("readonly", "readonly");
            }

            if(formAuthorizeRequired(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " required"):"required ";
                element.addAttribute("class",clsStr);
            }

            if(formAuthorizeHide(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " d-none"):"d-none ";
                element.addAttribute("class",clsStr);
            }

            if (key.equals("task_asignee")) {
                element.addAttribute("value","");
            }
        }

        //textarea 动态绑定
        List<Element> txtAreaElmts = node.elements("textarea");
        for (Element element : txtAreaElmts) {
            String key = element.attribute("name").getValue();
            element.setText(data == null ? "" : formDataValue(key, data));

            if(formAuthorizeRead(key, nodeList, taskDefKey)) {
                element.addAttribute("readonly", "readonly");
            }

            if(formAuthorizeRequired(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " required"):"required ";
                element.addAttribute("class",clsStr);
            }

            if(formAuthorizeHide(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " d-none"):"d-none ";
                element.addAttribute("class",clsStr);
            }
        }

        // select model 设置默认选中项
        List<Element> optElmts = node.elements("select");
        for (Element element : optElmts) {
            String key = element.attribute("name").getValue();
            Attribute multiple = element.attribute("multiple");
            String eleValue = data == null ? "" : formDataValue(key, data);

            List<Element> optionElement = element.elements("option");
            for (Element optElement : optionElement){
                Attribute atrOption = optElement.attribute("value");
                if(multiple !=null){
                    String[] split = eleValue.split(",");
                    for (int i = 0;i<split.length;i++){
                        if(StringUtils.isNotBlank(split[i]) && atrOption.getValue().equals(split[i])) {
                            optElement.addAttribute("selected", "selected");
                        }
                    }
                }
                if(StringUtils.isNotBlank(eleValue) && atrOption.getValue().equals(eleValue)) {
                    optElement.addAttribute("selected", "selected");
                    break;
                }

            }

            if(formAuthorizeRead(key, nodeList, taskDefKey)) {
                element.addAttribute("disabled", "disabled");
            }

            if(formAuthorizeRequired(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " required"):"required ";
                element.addAttribute("class",clsStr);
            }

            if(formAuthorizeHide(key, nodeList, taskDefKey)) {
                Attribute clsAttr = element.attribute("class");
                String clsStr = (clsAttr != null && StringUtils.isNotBlank(clsAttr.getValue()))?(clsAttr.getValue() + " d-none"):"d-none ";
                element.addAttribute("class",clsStr);
            }
        }

    }


    private static String formDataValue(String key, List<FormData> data) {
        for (FormData formData : data) {
            if (key.equals(formData.getFieldName())) {
                String fieldValue = StringUtils.isNotBlank(formData.getFieldValue())?formData.getFieldValue():formData.getFieldLargeValue();
                return fieldValue == null?"":fieldValue;
            }
        }
        return "";
    }

    private static boolean formAuthorizeRead(String key, List<TaskNode> taskNodes, String taskDefKey) {
        String resourceId = StringUtils.isBlank(taskDefKey)?"startevent1":taskDefKey;
        if (resourceId.equals("finish")) {// 流程表单详情查看
            return true;
        }
        if (resourceId.equals("edit")) {// 流程表单编辑数据
            return false;
        }

        for (TaskNode node : taskNodes) {
            if (key.equals(node.getFieldName()) && resourceId.toLowerCase().equals(node.getResourceId().toLowerCase())) {
                return node.getIsRead().equals("1");
            }
        }
        return false;
    }

    private static boolean formAuthorizeRequired(String key, List<TaskNode> taskNodes, String taskDefKey) {
        String resourceId = StringUtils.isBlank(taskDefKey)?"startevent1":taskDefKey;
        for (TaskNode node : taskNodes) {
            if (key.equals(node.getFieldName()) && resourceId.toLowerCase().equals(node.getResourceId().toLowerCase())) {
                return node.getIsRequire().equals("1");
            }
        }
        return false;
    }

    private static boolean formAuthorizeHide(String key, List<TaskNode> taskNodes, String taskDefKey) {
        String resourceId = StringUtils.isBlank(taskDefKey)?"startevent1":taskDefKey;
        for (TaskNode node : taskNodes) {
            if (key.equals(node.getFieldName()) && resourceId.toLowerCase().equals(node.getResourceId().toLowerCase())) {
                return node.getIsHide()==null?false:node.getIsHide().equals("1");
            }
        }
        return false;
    }

    private static String asXml(Document document){
        OutputFormat format = new OutputFormat();
        format.setEncoding("UTF-8");
        format.setExpandEmptyElements(true);
        StringWriter out = new StringWriter();
        XMLWriter writer = new XMLWriter(out, format);
        writer.setEscapeText(false);
        try {
            writer.write(document.getRootElement());
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toString();
    }

    public static boolean shortField(String source) {
        if (source == null) {
            return true;
        }

        try {
            return source.getBytes("utf-8").length > 255 ? false : true;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return true;
    }
}
